package cn.wuwenyao.patch.generator;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.wuwenyao.patch.generator.entity.PatchInfo;
import cn.wuwenyao.patch.generator.entity.ProjectInfo;
import cn.wuwenyao.patch.generator.entity.SourceMapper;
import cn.wuwenyao.patch.generator.enums.VersionManagerType;

/***
 * 补丁生成接口
 * 
 * @author wwy
 *
 */
public interface PatchGenerator {
	
	static final Logger LOG = LoggerFactory.getLogger(PatchGenerator.class);
	
	/***
	 * 是否支持版本管理软件
	 * 
	 * @param manageType
	 * @return
	 */
	public boolean support(VersionManagerType manageType);
	
	/***
	 * 生成补丁
	 * 
	 * @param projectInfo
	 *            项目信息
	 * @param patchInfo
	 *            补丁信息
	 * @throws Exception
	 */
	public void generatePatch(ProjectInfo projectInfo, PatchInfo patchInfo) throws Exception;
	
	/***
	 * 复制文件到补丁地址
	 * 
	 * @param fileName
	 * @param projectInfo
	 * @param patchInfo
	 */
	public default void copyFileToPatchDir(String fileName, ProjectInfo projectInfo, PatchInfo patchInfo) {
		if (fileName.endsWith("java")) {
			// java文件
			copyJavaFileToPatchDir(fileName, projectInfo, patchInfo);
		} else {
			// 普通文件
			copySimpleFileToPatchDir(fileName, projectInfo, patchInfo);
		}
	}
	
	/***
	 * 复制java文件到补丁地址
	 * 
	 * @param fileName
	 * @param projectInfo
	 * @param patchInfo
	 */
	public default void copyJavaFileToPatchDir(String fileName, ProjectInfo projectInfo, PatchInfo patchInfo) {
		List<SourceMapper> sourceMappers = projectInfo.getSourceMappers();
		for (SourceMapper sourceMapper : sourceMappers) {
			if (fileName.contains(sourceMapper.getSourceDir())) {
				String pureFileName = fileName.substring(
						fileName.indexOf(sourceMapper.getSourceDir()) + sourceMapper.getSourceDir().length());
				String pureFileParentDir = pureFileName.substring(0, pureFileName.lastIndexOf("/"));
				String pureFileTargetParentDir = projectInfo.getTargetBaseDir() + sourceMapper.getTargetDir()
						+ pureFileParentDir;
				String className = pureFileName.substring(pureFileName.lastIndexOf("/") + 1,
						pureFileName.lastIndexOf("."));
				File parentDir = new File(pureFileTargetParentDir);
				if (!parentDir.exists()) {
					LOG.error(String.format("文件夹:%s 不存在", pureFileTargetParentDir));
				}
				File[] classFiles = parentDir.listFiles(new JavaClassFileNameFilter(className));
				File targetDir = new File(patchInfo.getPatchFileDir() + sourceMapper.getPatchDir() + pureFileParentDir);
				if (classFiles != null) {
					for (File classFile : classFiles) {
						try {
							FileUtils.copyFileToDirectory(classFile, targetDir);
						} catch (IOException e) {
							LOG.error("复制文件错误", e);
						}
					}
				}
				break;
			}
		}
	}
	
	/**
	 * 复制一般文件到补丁地址
	 * 
	 * @param fileName
	 * @param projectInfo
	 * @param patchInfo
	 */
	public default void copySimpleFileToPatchDir(String fileName, ProjectInfo projectInfo, PatchInfo patchInfo) {
		List<SourceMapper> sourceMappers = projectInfo.getSourceMappers();
		for (SourceMapper sourceMapper : sourceMappers) {
			if (fileName.contains(sourceMapper.getSourceDir())) {
				String pureFileName = fileName.substring(
						fileName.indexOf(sourceMapper.getSourceDir()) + sourceMapper.getSourceDir().length());
				String filePath = projectInfo.getTargetBaseDir() + sourceMapper.getTargetDir() + pureFileName;
				
				File file = new File(filePath);
				if (!file.exists()) {
					LOG.error(String.format("文件:%s 不存在", filePath));
				}
				File targetFile = new File(patchInfo.getPatchFileDir() + sourceMapper.getPatchDir() + pureFileName);
				try {
					if (file.isFile()) {
						FileUtils.copyFile(file, targetFile);
					}
					if (file.isDirectory()) {
						FileUtils.copyDirectory(file, targetFile);
					}
					
				} catch (IOException e) {
					LOG.error("复制文件错误", e);
				}
				
				break;
			}
		}
	}
	
	public static class JavaClassFileNameFilter implements FilenameFilter {
		
		private String className;
		
		public JavaClassFileNameFilter() {
		}
		
		public JavaClassFileNameFilter(String className) {
			super();
			this.className = className;
		}
		
		@Override
		public boolean accept(File dir, String name) {
			if (name.equals(className + ".class") || name.startsWith(className + "$")) {
				return true;
			}
			return false;
		}
		
	}
	
}
